import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.AbstractAction;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.LayoutStyle;
import javax.swing.SwingConstants;

import javax.swing.WindowConstants;
import javax.swing.SwingUtilities;

import lejos.pc.comm.NXTCommException;

/**
 * This code was edited or generated using CloudGarden's Jigloo SWT/Swing GUI
 * Builder, which is free for non-commercial use. If Jigloo is being used
 * commercially (ie, by a corporation, company or business for any purpose
 * whatever) then you should purchase a license for each developer using Jigloo.
 * Please visit www.cloudgarden.com for details. Use of Jigloo implies
 * acceptance of these licensing terms. A COMMERCIAL LICENSE HAS NOT BEEN
 * PURCHASED FOR THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED LEGALLY FOR
 * ANY CORPORATE OR COMMERCIAL PURPOSE.
 */
public class GUItestTool extends javax.swing.JFrame implements ActionListener,
MouseListener {
	private JTextField commandBox;
	private JScrollPane jScrollPane1;
	private AbstractAction getLeftButton;
	private JButton leftButton;
	private AbstractAction abstractAction1;
	private JButton backwardButton;
	private AbstractAction moveForwardButton;
	private JButton forwardButton;
	private AbstractAction changeConnection;
	private JButton disconnectButton;
	private JButton CurveLButton;
	private AbstractAction curveRightAction;
	private AbstractAction curveLeftAction;
	private JButton curveRButton;
	private AbstractAction setSpeedAction;
	private JButton setSpeedButton;
	private JTextField setSpeedText;
	private AbstractAction abstractAction2;
	private AbstractAction getRightButton;
	private JButton rightButton;
	private JButton bluetoothButton;
	private static JTextArea inputList;
	private AbstractAction Stop;
	private AbstractAction connectBlue;
	private AbstractAction clearCommandLine;
	private JButton clearButton;
	private JButton bluetoothConn;
	private AbstractAction enterCommandLine;
	private static JTextArea displayList;
	private JButton inputButton;
	boolean bluetoothSig = true;

	int halt = 255000;
	int forward = 111000;
	int backward = 122000;
	int left = 222000;
	int right = 211000;
	int curveLeft = 122040; //go a little more than 3.75 cm
	int curveRight = 123040;
	
	/**
	 * Auto-generated main method to display this JFrame
	 * 
	 * @throws NXTCommException
	 */
	public static void main(String[] args) {
		//System.out.println("FOO");
		try {
			makeConnection();
			//while(Connection.isConnected()==true)
			{
				//System.out.println("FOO");
				Connection.read(inputList);
			}
		} catch (NXTCommException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				GUItestTool inst = new GUItestTool();
				inst.setLocationRelativeTo(null);
				inst.setVisible(true);
			}
		});
	}

	private static void makeConnection() throws NXTCommException {
		Connection.connect();
	}
	
	private static void disconnect() throws NXTCommException {
		Connection.closeConnection();
	}

	public GUItestTool() {
		super();
		initGUI();
	}

	private void initGUI() {
		try {
			{

			}
			getContentPane().setLayout(null);
			setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			getContentPane().add(getClearButton());
			getContentPane().add(stopButton());
			{
				commandBox = new JTextField();
				getContentPane().add(commandBox);
				getContentPane().add(getInputDisplay());
				getContentPane().add(getBluetoothButton());
				getContentPane().add(getForwardButton());
				getContentPane().add(getBackwardButton());
				getContentPane().add(getLeftButton());
				getContentPane().add(getRightButton());
				getContentPane().add(getDisconnectButton());
				getContentPane().add(getSetSpeedText());
				getContentPane().add(getSetSpeedButton());
				getContentPane().add(getCurveLButton());
				getContentPane().add(getCurveRButton());
				commandBox.setText("Type Command Here");
				commandBox.setBounds(12, 165, 151, 23);
			}

			pack();
			this.setSize(653, 335);
		} catch (Exception e) {
			// add your error handling code here
			e.printStackTrace();
		}
	}

	public String getCommandBox() {
		return commandBox.getText();
	}

	private AbstractAction getEnterCommandLine() {
		if (enterCommandLine == null) {
			enterCommandLine = new AbstractAction("Enter", null) {
				public void actionPerformed(ActionEvent evt) {
					String thecommand = getCommandBox();
					if(bluetoothSig ==false)
					{
						appendToDisplay("Bluetooth not connect");

					}
					else
					{
						//appendToDisplay("Command length is: " +thecommand.length()); //DEBUG
						if((thecommand.length()==6))
						{

							boolean found = false;
							String getBluetoothSignal = tempGenBluetoothString(thecommand);
							String passesBluetoothTest = tempParseBluetoothCommand(getBluetoothSignal,6);

							if (passesBluetoothTest.equals("error"))
							{
								appendToDisplay("Command is not Valid (error!)");
							}
							else if (validateInput(thecommand)) 
							{
								int thecommandInt = Integer.parseInt(thecommand);
								found = whatisCommand(thecommand, found);  //if it's not found, return false
								if (found == false)
								{
									appendToDisplay("Command is not in protocol");
								}
								try {
								Connection.send(thecommandInt);
							} catch (NXTCommException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
							}
						}
						else
						{
							appendToDisplay("Command is not Valid (not found)");
						}
					}
				}

				private String tempGenBluetoothString(String thecommand) {
					// TODO Auto-generated method stub
					// what would the hash value be
					int hashVal = thecommand.hashCode();
					String hashValS = Integer.toString(hashVal);
					// append it to the string
					String retString = thecommand.concat(hashValS);
					// This function returns a string "####hashvalue" which
					// represents what we think the bluetooth signal we're going
					// to receive from the control software would look like
					System.out.println("Send....");
					System.out.println("Encoding: "+thecommand);
					System.out.println("Hash Value: "+hashVal);
					System.out.println("encoding+hashvalue: "+retString);
					return retString;
				}
				private String tempParseBluetoothCommand(String blueTCmd,
						int intLength) {
					// check the checksum/hash value

					String hash = blueTCmd.substring(intLength, blueTCmd
							.length());
					System.out.println("Receive....");
					System.out.println("Hash: "+hash);
					String retString = blueTCmd.substring(0, (intLength));
					String checkHash = Integer.toString(retString.hashCode());
					System.out.println("retString: "+retString);
					System.out.println("checkHASH: "+checkHash);
					if (checkHash.equals(hash)) {
						// return the integer only
						System.out.println("Success hash equals!");
						System.out.println("======");
						return "equals";
					} 
					else
					{
						return "error";
					}
				}

				private boolean whatisCommand(String thecommand, boolean found) {
					// TODO Auto-generated method stub
					found = false;
					////////////////////Set Values
					if (thecommand.equals("111000")) {
						// send the hold value as a boolean somewhere for
						// movement
						appendToDisplay("Hold Move Forward");
						found = true;
					}
					if (thecommand.equals("112000")) {
						// send the hold value as a boolean somewhere for
						// movement
						appendToDisplay("Hold Move Backward");
						found = true;
					}
					if (thecommand.equals("122000")) //curve left
					{
						found = true;
					}
					if (thecommand.equals("123000")) //curve right
					{
						found = true;
					}
					if (thecommand.equals("222000")) {
						// send the hold value as a boolean somewhere for
						// movement
						appendToDisplay("Hold Turn Left");
						found = true;
					}
					if (thecommand.equals("211000")) {
						// send the hold value as a boolean somewhere for
						// movement
						appendToDisplay("Hold Turn Right");
						found = true;
					}
					if (thecommand.equals("322000")) {
						// send the hold value as a boolean somewhere for
						// movement
						appendToDisplay("Hold Arm Left");
						found = true;
					}
					if (thecommand.equals("311000")) {
						// send the hold value as a boolean somewhere for
						// movement
						appendToDisplay("Hold Arm Right");
						found = true;
					}
					if (thecommand.equals("111111")) {
						appendToDisplay("Request Robot Status");
						found = true;
					}
					if (thecommand.equals("123456")) {
						// send camera value boolean to true
						appendToDisplay("Request Last Command");
						found = true;
					}
					if (thecommand.equals("411000")) {
						// send the hold value as a boolean somewhere
						appendToDisplay("Hold Camera Up");
						found = true;
					}
					if (thecommand.equals("422000")) {
						// send the release value as a boolean somewhere
						appendToDisplay("Hold Camera Down");
						found = true;
					}
					if (thecommand.equals("511000")) {
						// send the hold value as a boolean somewhere
						appendToDisplay("Hold Camera Right");
						found = true;
					}
					if (thecommand.equals("522000")) {
						// send the release value as a boolean somewhere
						appendToDisplay("Hold Camera Left");
						found = true;
					}
					if (thecommand.equals("999999")) {
						// send the release value as a boolean somewhere
						appendToDisplay("Upload New Program");
						found = true;
					}

					if (thecommand.equals("255000")) {
						appendToDisplay("Stop");
						found = true;
					}
					/////////////////////Range Values

					if (thecommand.startsWith("101")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Move Forward "
								+ distance + "cm.");
						found = true;
					}
					if (thecommand.startsWith("102")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Move Backward "
								+ distance + "cm.");
						found = true;
					}
					if (thecommand.startsWith("122")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Curve Left "
								+ distance + "cm.");
						found = true;
					}
					if (thecommand.startsWith("123")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Curve Right "
								+ distance + "cm.");
						found = true;
					}
					if (thecommand.startsWith("202")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Turn Left "
								+ distance + "cm.");
						found = true;
					}
					if (thecommand.startsWith("201")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Turn Right "
								+ distance + "cm.");
						found = true;
					}
					if (thecommand.startsWith("302")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Arm Left "
								+ distance + "degrees.");
						found = true;
					}
					if (thecommand.startsWith("301")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Arm Right "
								+ distance + "degrees.");
						found = true;
					}
					if (thecommand.startsWith("401")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Camera Tilt Up "
								+ distance + "degrees.");
						found = true;
					}
					if (thecommand.startsWith("402")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Camera Tilt Down "
								+ distance + "degrees.");
						found = true;
					}
					if (thecommand.startsWith("502")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Camera Tilt Left "
								+ distance + "degrees.");
						found = true;
					}
					if (thecommand.startsWith("501")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
						appendToDisplay("Camera Tilt Right "
								+ distance + "degrees.");
						found = true;
					}
					if (thecommand.startsWith("701")) {
						String distanceString = thecommand.substring(3, 6);
						int distance = Integer.parseInt(distanceString);
						// send distance to the a sensor Class
							appendToDisplay("Set Speed "
									+ distance + " degrees per second");
							found = true;
					}
					return found;
				}

				private boolean validateInput(String thecommand) {
					Pattern pattern = Pattern.compile("\\d+");
					Matcher matcher = pattern.matcher(thecommand); // only
					// digits
					if (matcher.matches()) {
						int thecommandInt = Integer.parseInt(thecommand);
						if (thecommandInt<=99999 &&thecommandInt>999999)
						{
							// appendToDisplay("Command is not valid");
							return false;
						}
						return true;
					} else {
						appendToDisplay("Command is not valid");
					}

					return false;

				}
			};
		}
		return enterCommandLine;
	}

	private AbstractAction getClearCommandLine() {
		if (clearCommandLine == null) {
			clearCommandLine = new AbstractAction("Clear", null) {
				public void actionPerformed(ActionEvent evt) {
					commandBox.setText("");
				}
			};
		}
		return clearCommandLine;
	}
	
	void appendToInputDisplay(int fromRobot){
		String inputInt = Integer.toString(fromRobot);
		inputList.append(inputInt);
		inputList.append("\n");
	}

	void appendToDisplay(String str) {
		displayList.append(str);
		displayList.append("\n");
	}

	private JScrollPane getJScrollPane1() {
		if (jScrollPane1 == null) {
			jScrollPane1 = new JScrollPane();
			jScrollPane1.setBounds(12, 22, 290, 137);
			{
				displayList = new JTextArea();
				jScrollPane1.setViewportView(displayList);
				displayList.setEditable(false);
				displayList.setLineWrap(true);
			}
		}
		return jScrollPane1;
	}

	private JButton stopButton() throws NXTCommException {
		if (bluetoothConn == null) {
			bluetoothConn = new JButton();
			bluetoothConn.setText("Stop");
			bluetoothConn.setAction(getStop());
			bluetoothConn.setBounds(375, 192, 93, 48);
		}
		{
			inputButton = new JButton();
			getContentPane().add(inputButton);
			getContentPane().add(getJScrollPane1());
			inputButton.setText("Received Input:");
			inputButton.setAction(getEnterCommandLine());
			inputButton.setBounds(169, 165, 111, 41);
			/*
			 * inputButton.registerKeyboardAction(inputButton.getActionForKeyStroke
			 * ( KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false)),
			 * KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false),
			 * JComponent.WHEN_FOCUSED);
			 * inputButton.registerKeyboardAction(inputButton
			 * .getActionForKeyStroke( KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,
			 * 0, true)), KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true),
			 * JComponent.WHEN_FOCUSED);
			 */
		}
		return bluetoothConn;
	}

	private JButton getClearButton() {
		if (clearButton == null) {
			clearButton = new JButton();
			clearButton.setText("Clear");
			clearButton.setAction(getClearCommandLine());
			clearButton.setBounds(169, 211, 111, 42);
		}
		return clearButton;
	}


	@Override
	public void actionPerformed(ActionEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub

	}
	
	private AbstractAction getStop() {
		if(Stop == null) {
			Stop = new AbstractAction("Stop", null) {
				public void actionPerformed(ActionEvent evt) {
					try {
						Connection.send(halt);
						appendToDisplay("Stop");
					} catch (NXTCommException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}
		return Stop;
	}
	
	public JTextArea getInputDisplay() {
		if(inputList == null) {
			inputList = new JTextArea();
			inputList.setText("Inputs:");
			inputList.setBounds(478, 17, 147, 131);
		}
		return inputList;
	}
	
	private JButton getBluetoothButton() {
		if(bluetoothButton == null) {
			bluetoothButton = new JButton();
			bluetoothButton.setText("Connect Bluetooth");
			bluetoothButton.setBounds(12, 224, 141, 28);
			bluetoothButton.setAction(getChangeConnection());
		}
		return bluetoothButton;
	}
	
	private AbstractAction getChangeConnection() {
		if(changeConnection == null) {
			changeConnection = new AbstractAction("Connect Bluetooth", null) {
				public void actionPerformed(ActionEvent evt) {
					try {
						makeConnection();
					} catch (NXTCommException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}
		return changeConnection;
	}
	
	private JButton getForwardButton() {
		if(forwardButton == null) {
			forwardButton = new JButton();
			forwardButton.setText("Forward");
			forwardButton.setBounds(372, 148, 95, 33);
			forwardButton.setAction(getMoveForwardButton());
		}
		return forwardButton;
	}
	
	private AbstractAction getMoveForwardButton() {
		if(moveForwardButton == null) {
			moveForwardButton = new AbstractAction("Forward", null) {
				public void actionPerformed(ActionEvent evt) {
					try {
						Connection.send(forward);
						appendToDisplay("Forward");
					} catch (NXTCommException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}
		return moveForwardButton;
	}
	
	private JButton getBackwardButton() {
		if(backwardButton == null) {
			backwardButton = new JButton();
			backwardButton.setText("Backward");
			backwardButton.setBounds(375, 251, 93, 35);
			backwardButton.setAction(getMoveBackwardButton());
		}
		return backwardButton;
	}
	
	private AbstractAction getMoveBackwardButton() {
		if(abstractAction1 == null) {
			abstractAction1 = new AbstractAction("Backward", null) {
				public void actionPerformed(ActionEvent evt) {
					try {
						Connection.send(backward);
						appendToDisplay("Backward");
					} catch (NXTCommException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
			};
		}
		return abstractAction1;
	}
	
	private JButton getLeftButton() {
		if(leftButton == null) {
			leftButton = new JButton();
			leftButton.setText("L");
			leftButton.setBounds(321, 187, 43, 61);
			leftButton.setAction(getGetLeftButton());
		}
		return leftButton;
	}
	
	private AbstractAction getGetLeftButton() {
		if(getLeftButton == null) {
			getLeftButton = new AbstractAction("L", null) {
				public void actionPerformed(ActionEvent evt) {
					try {
						Connection.send(left);
						appendToDisplay("Left");
					} catch (NXTCommException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}
		return getLeftButton;
	}
	
	private JButton getRightButton() {
		if(rightButton == null) {
			rightButton = new JButton();
			rightButton.setText("R");
			rightButton.setBounds(479, 186, 43, 59);
			rightButton.setAction(getGetRightButton());
		}
		return rightButton;
	}
	
	private AbstractAction getGetRightButton() {
		if(getRightButton == null) {
			getRightButton = new AbstractAction("R", null) {
				public void actionPerformed(ActionEvent evt) {
					try {
						Connection.send(right);
						appendToDisplay("Right");
					} catch (NXTCommException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}
		return getRightButton;
	}
	
	private JButton getDisconnectButton() {
		if(disconnectButton == null) {
			disconnectButton = new JButton();
			disconnectButton.setText("Disconnect");
			disconnectButton.setBounds(12, 263, 141, 23);
			disconnectButton.setAction(getDisconnect());
		}
		return disconnectButton;
	}
	
	private AbstractAction getDisconnect() {
		if(abstractAction2 == null) {
			abstractAction2 = new AbstractAction("Disconnect", null) {
				public void actionPerformed(ActionEvent evt) {
					try {
						disconnect();
					} catch (NXTCommException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}
		return abstractAction2;
	}
	
	private JTextField getSetSpeedText() {
		if(setSpeedText == null) {
			setSpeedText = new JTextField();
			setSpeedText.setBounds(308, 40, 52, 23);
		}
		return setSpeedText;
	}
	
	private JButton getSetSpeedButton() {
		if(setSpeedButton == null) {
			setSpeedButton = new JButton();
			setSpeedButton.setText("Set Speed %");
			setSpeedButton.setBounds(366, 40, 106, 23);
			setSpeedButton.setAction(getSetSpeedAction());
		}
		return setSpeedButton;
	}
	
	private AbstractAction getSetSpeedAction() {
		if(setSpeedAction == null) {
			setSpeedAction = new AbstractAction("Set Speed %", null) {
				public void actionPerformed(ActionEvent evt) {
					String speedInput = setSpeedText.getText();
					if(speedInput.length()==2)
					{
						speedInput = "7010"+speedInput;
					}
					if(speedInput.length()==3)
					{
						speedInput = "701"+speedInput;
					}
					int speedInputInt = Integer.parseInt(speedInput);
					try {
						Connection.send(speedInputInt);
						appendToDisplay("Set Speed to: "+speedInput+"%");
						
					} catch (NXTCommException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}
		return setSpeedAction;
	}
	
	private JButton getCurveLButton() {
		if(CurveLButton == null) {
			CurveLButton = new JButton();
			CurveLButton.setText("c L");
			CurveLButton.setBounds(300, 146, 67, 37);
			CurveLButton.setAction(getCurveLeftAction());
		}
		return CurveLButton;
	}
	
	private JButton getCurveRButton() {
		if(curveRButton == null) {
			curveRButton = new JButton();
			curveRButton.setText("c R");
			curveRButton.setBounds(472, 148, 65, 33);
			curveRButton.setAction(getCurveRightAction());
		}
		return curveRButton;
	}
	
	private AbstractAction getCurveLeftAction() {
		if(curveLeftAction == null) {
			curveLeftAction = new AbstractAction("c L", null) {
				public void actionPerformed(ActionEvent evt) {
					try {
						Connection.send(curveLeft);
					} catch (NXTCommException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}
		return curveLeftAction;
	}
	
	private AbstractAction getCurveRightAction() {
		if(curveRightAction == null) {
			curveRightAction = new AbstractAction("c R", null) {
				public void actionPerformed(ActionEvent evt) {
					try {
						Connection.send(curveRight);
					} catch (NXTCommException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			};
		}
		return curveRightAction;
	}

}
